/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 * Author: Huawei OS Kernel Lab
 * Create: Thu Aug 15 16:14:23 2023
 */

#ifndef __LIBLINUX_UACCESS_H__
#define __LIBLINUX_UACCESS_H__

#define __put_user			put_user
#define __get_user			get_user
#define copy_to_user			__copy_to_user
#define copy_from_user			__copy_from_user
#define copy_in_user			__copy_in_user
#define clear_user			__clear_user
#define __copy_to_user			__arch_copy_to_user
#define __copy_from_user		__arch_copy_from_user
#define __copy_to_user_inatomic		__arch_copy_to_user
#define __copy_from_user_inatomic	__arch_copy_from_user

#define put_user(x, ptr)						\
({									\
	__typeof__(*(ptr)) __val = (__typeof__(*(ptr)))(x);		\
	__typeof__(*(ptr)) __user *__p = (ptr);				\
	liblinux_pal_copy_to_user(__p, &__val, sizeof(*__p)) < 0 ?	\
		-EFAULT : 0;						\
})

#define get_user(x, ptr)						\
({									\
	__typeof__(*(ptr)) __user *__p = (ptr);				\
	liblinux_pal_copy_from_user((void *)&(x), __p, sizeof(*__p)) < 0 ?	\
		((x) = 0, -EFAULT) : 0;					\
})

static inline
unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from,
						 unsigned long n)
{
	if (get_fs() == USER_DS) {
		if (liblinux_pal_copy_from_user(to, from, n) < 0) {
			/* security hole - plug it */
			memset(to, 0, n);
			return n;
		}
	} else {
		memcpy(to, from, n);
	}

	return 0;
}

static inline
unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from,
					       unsigned long n)
{
	if (get_fs() == USER_DS) {
		if (liblinux_pal_copy_to_user(to, from, n) < 0)
			return n;
	} else {
		memcpy(to, from, n);
	}

	return 0;
}

static inline
unsigned long __must_check __copy_in_user(void __user *to, const void __user *from,
					  unsigned long n)
{
	int ret;

	ret = liblinux_pal_copy_in_user(to, from, n);
	if (ret < 0)
		return n;

	return 0;
}

static inline unsigned long __must_check __clear_user(void __user *to, unsigned long n)
{
	printk("~~ UN-IMPL~~: %s()\n", __func__);
	return n;
}

#endif		/* __LIBLINUX_UACCESS_H__ */
